package cn.signalpha.modules.shop.service;

import cn.signalpha.common.utils.Assert;
import cn.signalpha.core.log.exception.ServiceException;
import cn.signalpha.core.tool.utils.*;
import cn.signalpha.modules.shop.entity.*;
import cn.signalpha.modules.shop.mapper.GoodsMapper;
import cn.signalpha.modules.shop.vo.GoodsListVO;
import cn.signalpha.modules.shop.vo.GoodsSpecKeyVO;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;


/**
 * 商品 服务类
 *
 * @author suguangjun
 */
@Service
@AllArgsConstructor
public class GoodsService extends ServiceImpl<GoodsMapper, Goods> {

    private final GoodsSkuService goodsSkuService;
    private final GoodsSpecService goodsSpecService;
    private final GoodsAttrService goodsAttrService;

	/**
	 * 自定义分页
	 */
    public IPage<GoodsListVO> selectGoodsPage(IPage<GoodsListVO> page, Map<String, Object> params) {
        return page.setRecords(baseMapper.selectGoodsPage(page, params));
    }

	/**
	 * 自定义列表
	 */
	public List<GoodsListVO> selectGoodsList(Map<String, Object> params) {
		return baseMapper.selectGoodsPage(null, params);
	}

	/**
	 * 自定义Wrapper
	 */
	public QueryWrapper<Goods> selectGoodsWrapper(Map<String, Object> params) {
		QueryWrapper<Goods> wrapper = Wrappers.query();
		wrapper.lambda().in(ObjectUtil.isNotEmpty(params.get("ids")), Goods::getId, Func.toLongList(String.valueOf(params.get("ids"))));
		wrapper.lambda().notIn(ObjectUtil.isNotEmpty(params.get("idsNe")), Goods::getId, Func.toLongList(String.valueOf(params.get("idsNe"))));
		wrapper.lambda().eq(ObjectUtil.isNotEmpty(params.get("sellerId")), Goods::getSellerId, params.get("sellerId"));
		wrapper.lambda().eq(ObjectUtil.isNotEmpty(params.get("kind")), Goods::getKind, params.get("kind"));
		wrapper.lambda().eq(ObjectUtil.isNotEmpty(params.get("type")), Goods::getType, params.get("type"));
		wrapper.lambda().eq(ObjectUtil.isNotEmpty(params.get("status")), Goods::getStatus, params.get("status"));
		wrapper.lambda().eq(ObjectUtil.isNotEmpty(params.get("brandId")), Goods::getBrandId, params.get("brandId"));
//		wrapper.lambda().apply(ObjectUtil.isNotEmpty(params.get("categoryId")), "FIND_IN_SET ('" + params.get("categoryId") + "',category_id)");
//		wrapper.lambda().apply(ObjectUtil.isNotEmpty(params.get("sellerGoodsCategoryId")), "FIND_IN_SET ('" + params.get("sellerGoodsCategoryId") + "',seller_goods_category_id)");
		wrapper.lambda().like(ObjectUtil.isNotEmpty(params.get("categoryId")), Goods::getCategoryId, params.get("categoryId"));
		wrapper.lambda().like(ObjectUtil.isNotEmpty(params.get("sellerGoodsCategoryId")), Goods::getSellerGoodsCategoryId, params.get("sellerGoodsCategoryId"));
		wrapper.lambda().like(ObjectUtil.isNotEmpty(params.get("name")), Goods::getName, params.get("name"));
		wrapper.lambda().like(ObjectUtil.isNotEmpty(params.get("sn")), Goods::getSn, params.get("sn"));
		wrapper.lambda().eq(ObjectUtil.isNotEmpty(params.get("isHot")), Goods::getIsHot, params.get("isHot"));
		wrapper.lambda().eq(ObjectUtil.isNotEmpty(params.get("isPush")), Goods::getIsPush, params.get("isPush"));
		wrapper.lambda().ge(ObjectUtil.isNotEmpty(params.get("goodsPriceBegin")), Goods::getGoodsPrice, params.get("goodsPriceBegin"));
		wrapper.lambda().le(ObjectUtil.isNotEmpty(params.get("goodsPriceEnd")), Goods::getGoodsPrice, params.get("goodsPriceEnd"));

		String orderByAsc = String.valueOf(params.get("orderByAsc"));
		if(StringUtil.isNotBlank(orderByAsc)){
			if("salesVolume".contains(orderByAsc)){
				wrapper.orderByAsc("sales_volume + sales_volume_virtual");
			}else if("goodsPrice".contains(orderByAsc)){
				wrapper.orderByAsc("goods_price");
			}else if("sort".contains(orderByAsc)){
				wrapper.orderByAsc("sort");
			}
		}
		String orderByDesc = String.valueOf(params.get("orderByDesc"));
		if(StringUtil.isNotBlank(orderByDesc)){
			if("salesVolume".contains(orderByDesc)){
				wrapper.orderByDesc("sales_volume + sales_volume_virtual");
			}else if("goodsPrice".contains(orderByDesc)){
				wrapper.orderByDesc("goods_price");
			}else if("sort".contains(orderByDesc)){
				wrapper.orderByDesc("sort");
			}
		}
		wrapper.lambda().orderByDesc(Goods::getId);
		return wrapper;
	}


	/**
	 * 金额统计
	 */
	public Double sumByParams(Map<String, Object> params) {
		return sumByParams(params, "goods_price");
	}

	/**
	 * 金额统计
	 */
	public Double sumByParams(Map<String, Object> params, String field) {
		QueryWrapper<Goods> wrapper = selectGoodsWrapper(params);
		wrapper.select(StringUtil.format("ifnull(sum({}),0) as total", field));
		return Double.valueOf(getMap(wrapper).get("total").toString());
	}

	/**
	 * 数量统计
	 */
	public long countByParams(Map<String, Object> params) {
		return count(selectGoodsWrapper(params));
	}

	/**
	 * 减少库存
	 */
	public int subtractStocks(Long goodsId, Integer stock) {
		return baseMapper.subtractStocks(goodsId, stock);
	}

	/**
	 * 返回库存
	 */
	public int returnStock(Map<Long, Integer> goodsCollect) {
		return baseMapper.returnStock(goodsCollect);
	}

	/**
	 * 增加销量
	 */
	public int addSalesVolume(Map<Long, Integer> goodsCollect){
		return baseMapper.addSalesVolume(goodsCollect);
	}

    /**
     * 保存商品
     */
    @Transactional(rollbackFor = Exception.class)
    public Long saveGoods(Goods goodsDTO) {
        Goods goods = Objects.requireNonNull(BeanUtil.copy(goodsDTO, Goods.class));
		if(ObjectUtil.isEmpty(goods.getSellerId())){
			goods.setSellerId(0L);
		}
        goods.setCreateTime(DateUtil.now());
        goods.setUpdateTime(DateUtil.now());
        this.save(goods);

		//保存规格
		if(CollectionUtil.isNotEmpty(goodsDTO.getGoodsSpecKeyList())){
			verifyGoodsSpec(goodsDTO.getGoodsSpecKeyList());
			saveGoodsSpec(goodsDTO.getGoodsSpecKeyList(), goods.getId());
		}
		//保存SKU
		if(CollectionUtil.isNotEmpty(goodsDTO.getGoodsSkuList())){
			goodsDTO.getGoodsSkuList().forEach(goodsSku -> goodsSku.setId(null));
			saveGoodsSku(goodsDTO.getGoodsSkuList(), goods.getId());
		}else{
			throw new ServiceException("添加失败，未获取到商品sku");
		}
		//保存商品属性
		if(CollectionUtil.isNotEmpty(goodsDTO.getGoodsAttrList())){
			goodsDTO.getGoodsAttrList().forEach(goodsSku -> goodsSku.setId(null));
			saveGoodsAttr(goodsDTO.getGoodsAttrList(), goods.getId());
		}
        return goods.getId();
    }

    /**
     * 编辑商品
     */
    @Transactional(rollbackFor = Exception.class)
    public Long updateGoods(Goods goodsDTO) {
        Goods goods = this.getById(goodsDTO.getId());
        Assert.isNull(goods, "商品不存在");

        Goods goodsUpdate = Objects.requireNonNull(BeanUtil.copy(goodsDTO, Goods.class));
		if(ObjectUtil.isEmpty(goodsUpdate.getSellerId())){
			goods.setSellerId(0L);
		}
        goodsUpdate.setUpdateTime(DateUtil.now());
        this.updateById(goodsUpdate);

		//清除商格品原有的规格属性
		goodsSpecService.removeByGoodsId(goodsDTO.getId());
		goodsSkuService.removeByGoodsId(goodsDTO.getId());
		goodsAttrService.removeByGoodsId(goodsDTO.getId());

		//保存规格
		if(CollectionUtil.isNotEmpty(goodsDTO.getGoodsSpecKeyList())){
			verifyGoodsSpec(goodsDTO.getGoodsSpecKeyList());
			saveGoodsSpec(goodsDTO.getGoodsSpecKeyList(), goods.getId());
		}
		//保存SKU
		if(CollectionUtil.isNotEmpty(goodsDTO.getGoodsSkuList())){
			saveGoodsSku(goodsDTO.getGoodsSkuList(), goods.getId());
		}else{
			throw new ServiceException("编辑失败，未获取到商品sku");
		}
		//保存商品属性
		if(CollectionUtil.isNotEmpty(goodsDTO.getGoodsAttrList())){
			saveGoodsAttr(goodsDTO.getGoodsAttrList(), goods.getId());
		}
		return goods.getId();
    }


    /**
     * 保存商品属性
     */
    private void saveGoodsAttr(List<GoodsAttr> goodsAttrList, Long goodsId) {
        if(CollectionUtil.isNotEmpty(goodsAttrList)){
            for(GoodsAttr goodsAttr : goodsAttrList){
				goodsAttr.setId(null);
                goodsAttr.setGoodsId(goodsId);
            }
            goodsAttrService.saveBatch(goodsAttrList);
        }
    }

    /**
     * 保存sku
     */
    private void saveGoodsSku(List<GoodsSku> goodsSkuList, Long goodsId) {
		int goodsStockTotal = 0;
		double goodsPrice = goodsSkuList.get(0).getGoodsPrice();
		double marketPrice = goodsSkuList.get(0).getMarketPrice();
		for(GoodsSku goodsSkuDto : goodsSkuList){
			goodsSkuDto.setId(null);
			goodsSkuDto.setGoodsId(goodsId);
			goodsStockTotal = goodsStockTotal + goodsSkuDto.getStock();
			if(goodsSkuDto.getGoodsPrice() < goodsPrice){
				goodsPrice = goodsSkuDto.getGoodsPrice();
				marketPrice = goodsSkuDto.getMarketPrice();
			}

			//初始化规格
			if(StringUtil.isBlank(goodsSkuDto.getSpec())){
				goodsSkuDto.setSpec(StringPool.EMPTY_JSON);
			}
		}
		goodsSkuService.saveBatch(goodsSkuList);

		//更新商品总库存和最低价格
		updateById(Goods.builder().id(goodsId).goodsPrice(goodsPrice).marketPrice(marketPrice).stock(goodsStockTotal).build());
    }

    /**
     * 保存规格
     */
    private void saveGoodsSpec(List<GoodsSpecKeyVO> goodsSpecKeyList, Long goodsId) {
        if(CollectionUtil.isNotEmpty(goodsSpecKeyList)){
            List<GoodsSpec> goodsSpecList = new LinkedList<>();
            for(GoodsSpecKeyVO goodsSpecKey : goodsSpecKeyList){
                for(GoodsSpec goodsSpec : goodsSpecKey.getGoodsSpecList()){
					goodsSpec.setId(null);
                    goodsSpec.setGoodsId(goodsId);
                    goodsSpec.setSpecKey(goodsSpecKey.getSpecKey());
                    goodsSpecList.add(goodsSpec);
                }
            }
            goodsSpecService.saveBatch(goodsSpecList);
        }
    }

    /**
     * 校验规格 规格key与key不能重复， key里面value与value不能重复
     */
    private void verifyGoodsSpec(List<GoodsSpecKeyVO> goodsSpecKeyList) {
        if(goodsSpecKeyList != null && goodsSpecKeyList.size() > 0){
            List<String> key = new ArrayList<>();
            for(GoodsSpecKeyVO goodsSpecKeyDto : goodsSpecKeyList){
                key.add(goodsSpecKeyDto.getSpecKey());
                List<String> value = new ArrayList<>();
                for(GoodsSpec goodsSpec : goodsSpecKeyDto.getGoodsSpecList()){
                    value.add(goodsSpec.getSpecValue());
                }

                if(value.stream().distinct().count() < value.size()){
                    throw new ServiceException("规格 " + goodsSpecKeyDto.getSpecKey() + " 下不能有重复值");
                }
            }
            if(key.stream().distinct().count() < key.size()){
                throw new ServiceException("规格名不能重复");
            }
        }
    }

    /**
     * 格式化商品规格
     */
    public List<GoodsSpecKeyVO> formattingGoodsSpec(List<GoodsSpec> goodsSpecList) {
        if(goodsSpecList.size() <= 0){
            return new ArrayList<>();
        }
        Map<String, GoodsSpecKeyVO> map = new HashMap<>();
        List<GoodsSpecKeyVO> goodsSpecKeyList = new LinkedList<>();
        for(GoodsSpec goodsSpec : goodsSpecList){
            String specKey = goodsSpec.getSpecKey();
            GoodsSpecKeyVO goodsSpecKeyVO = map.get(specKey);
            if(goodsSpecKeyVO == null){
                goodsSpecKeyVO = new GoodsSpecKeyVO();
                goodsSpecKeyVO.setSpecKey(specKey);
                List<GoodsSpec> valueList = new LinkedList<>();
                valueList.add(goodsSpec);
                goodsSpecKeyVO.setGoodsSpecList(valueList);
                map.put(specKey, goodsSpecKeyVO);
                goodsSpecKeyList.add(goodsSpecKeyVO);
            }else{
                List<GoodsSpec> valueList = goodsSpecKeyVO.getGoodsSpecList();
                valueList.add(goodsSpec);
            }
        }
        return goodsSpecKeyList;
    }

}
